package com.jyt.motor.service.impl;

import com.jyt.motor.dao.*;
import com.jyt.motor.model.*;
import com.jyt.motor.service.ReceiveEBTService;
import com.jyt.motor.util.CRC16;
import com.jyt.motor.util.SqlServer;
import com.jyt.motor.util.StringUtils;
import gnu.io.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class ReceiveEBTServiceImp extends ReceiveServiceImp implements ReceiveEBTService {

    @Value("${motor.rxdCOMe}")
    private String rxdCOMe;
    @Value("${motor.rxdIP}")
    private String rxdIP;
    @Value("${motor.rxdPort}")
    private String rxdPort;


    private static volatile BlockingQueue<RawData> queue = new LinkedBlockingQueue<RawData>(60);
    private static Semaphore semaphore = new Semaphore(1);
    private static SerialPort serialPort;
    private Enumeration<CommPortIdentifier> portList;
    private boolean isTimeout = false;
    boolean isOpen = false;
    private OutputStream outputStream;
    private InputStream inputStream;
    //private static String currentCommand = "";
    private String addr;
    public static final int ALERT_CALSS_EXCEED = 1;
    public static final int ALERT_CALSS_OFFLINE = 3;

    private int offlineTimes = 0;
    public static Map<Integer, Integer> motorOfflineTimes = new HashMap<>();

    private int exceptionTimes = 0;
    public static Map<Integer, Integer> motorExceptionTimes = new HashMap<>();

    private int recoveryTimes = 0;
    public static Map<Integer, Integer> motorRecoveryTimes = new HashMap<>();
    public static Integer converterTypeE = 0;

    public static Map<Integer, Integer> motorRecTimes = new HashMap<>();

    @Autowired
    MoMotorsMapper motorsMapper;

    @Autowired
    MoConverterMapper converterMapper;

    @Autowired
    MoDataRecMapper dataRecMapper;

    @Autowired
    MoAlertRecMapper alertRecMapper;

    @Autowired
    SysConfigMapper sysConfigMapper;

    @Autowired
    AlarmLampServiceImpSerialPort alarmLampServiceImpSerialPort;

    @Autowired
    SqlServer sqlServer;

    public int getSaveTimes() {
        try {
            return 60 / getGetDataCron();
        } catch (Exception e) {
            log.error(e.getMessage());
            return 1;
        }
    }

    public int getOfflineTimes() {
        if (offlineTimes == 0) {
            offlineTimes = Integer.parseInt(sysConfigMapper.selectByConfKey("motor_offline_times").getConfValue().trim());
        }
        return offlineTimes;
    }

    public int getExceptionTimes() {
        if (exceptionTimes == 0) {
            exceptionTimes = Integer.parseInt(sysConfigMapper.selectByConfKey("motor_exception_times").getConfValue().trim());
        }
        return exceptionTimes;
    }

    public int getRecoveryTimes() {
        if (recoveryTimes == 0) {
            recoveryTimes = Integer.parseInt(sysConfigMapper.selectByConfKey("motor_recovery_times").getConfValue().trim());
        }
        return recoveryTimes;
    }

    public int getSaveDataCron() {
        if (saveDataCron == 0) {
            saveDataCron = Integer.parseInt(sysConfigMapper.selectByConfKey("save_data_ebt_cron").getConfValue().trim());
        }
        return saveDataCron;
    }

    public String getMobiles() {
        if (StringUtils.isBlank(mobiles)) {
            mobiles = sysConfigMapper.selectByConfKey("abnormal_SMS_mobiles").getConfValue().trim();
        }
        return mobiles;
    }

    public void clearMobiles() {
        mobiles = "";
    }

    public void clearSaveDataCron() {
        saveDataCron = 0;
    }

    public int getGetDataCron() {
        if (getDataCron == 0) {
            getDataCron = Integer.parseInt(sysConfigMapper.selectByConfKey("get_data_ebt_cron").getConfValue().trim());
        }
        return getDataCron;
    }

    public void clearGetDataCron() {
        getDataCron = 0;
    }

    private Socket socket = null;
    private int length = 0;
    private byte[] content = new byte[100];

    @Override
    public boolean getData() {
        if(StringUtils.isBlank(rxdIP.trim())||StringUtils.isBlank(rxdPort))
        {
            log.error("rxdIP or rxdPort is null!!!");
            return true;
        }
        List<MoConverter> converters = converterMapper.getInUseConverter(0);
        if (converters != null && converters.size() > 0) {
            try {
                socket = new Socket(rxdIP.trim(), Integer.parseInt(rxdPort.trim()));
                for (MoConverter converter : converters) {
                    byte[] data = socketData(converter.getCommand());
                    if(data==null)//模块离线
                    {
                        List<MotorMonitor> motorMonitors = motorsMapper.motorMoniSelect(converter.getCommand().substring(0, 2), converterTypeE);
                        List<MoAlertRec> moAlertRecs = new ArrayList<>();
                        List<Integer> offlineMotorIds = new ArrayList<>();
                        for (MotorMonitor motorMonitor : motorMonitors) {
                            if (motorMonitor.getMoState() != 3 && motorMonitor.getMoState() != 0) {
                                //连续异常 再报警
                                if (motorOfflineTimes.get(motorMonitor.getMoId()) == null) {
                                    motorOfflineTimes.put(motorMonitor.getMoId(), 1);
                                } else if (motorOfflineTimes.get(motorMonitor.getMoId()) < getOfflineTimes()) {
                                    motorOfflineTimes.put(motorMonitor.getMoId(), motorOfflineTimes.get(motorMonitor.getMoId()) + 1);
                                } else if (motorOfflineTimes.get(motorMonitor.getMoId()) >= getOfflineTimes()) {
                                    if (isAlarmOffline != 0) {
                                        MoAlertRec alertRec = new MoAlertRec(ALERT_CALSS_OFFLINE, motorMonitor.getMoId(), motorMonitor.getMoName(), motorMonitor.getAreaId(),
                                                motorMonitor.getAreaName(), new Date(), BigDecimal.valueOf(0), motorMonitor.getUpperLimit(), motorMonitor.getLowerLimit(), 0,
                                                motorMonitor.getAreaName() + "->" + motorMonitor.getMoName() + "馬達離線，沒有數據！");
                                        moAlertRecs.add(alertRec);
                                    }
                                    offlineMotorIds.add(motorMonitor.getMoId());
                                    motorOfflineTimes.put(motorMonitor.getMoId(), 0);
                                }
                            }
                        }
                        if (moAlertRecs.size() > 0) {
                            alertRecMapper.insertBatch(moAlertRecs);
                        }
                        if (offlineMotorIds.size() > 0) {
                            motorsMapper.updateStateByIds(0, "gray", offlineMotorIds);
                        }
                    } else if (CRC16.checkCRC2(data)) {
                        addr = CRC16.bytesToString(new byte[]{data[0]}).trim();
                        int[] values = CRC16.byte2Info(Arrays.copyOfRange(data, 3, 7));
                        RawData rawData = new RawData(addr, values[0], values[1], new Date());
                        if (!queue.offer(rawData)) {
                            log.error("Data queue full!!!size:" + queue.size());
                            queue.poll();
                            queue.offer(rawData);
                        }
                        log.info("Receive data:addr=" + rawData.getAddr() + ",data1=" + rawData.getData().get(0) + ",data2=" + rawData.getData().get(1) + "------queue size:" + queue.size());
                    }
                }
                closeSocket();
            } catch (UnknownHostException e) {
                log.error("EBT串口服务器连接失败！！！"+e.getMessage());
                closeSocket();
                e.printStackTrace();
            } catch (IOException e) {
                log.error(e.getMessage());
                closeSocket();
                e.printStackTrace();
            }
        }
        return true;
    }

    private byte[] socketData(String comm)  {
        try {
            long time = new Date().getTime();
            //发送命令接收数据
            length = 0;
            //if (outputStream == null) {
                outputStream = socket.getOutputStream();
           // }
            outputStream.write(CRC16.command2Bytes(comm));
            outputStream.flush();
            socket.setKeepAlive(true);
           // if (inputStream == null) {
                inputStream = socket.getInputStream();
           // }
            while (inputStream.available() == 0) {
                Thread.sleep(100);
                if (new Date().getTime() >= time + receiveDataTimeout) {
                    log.error("Receiving data timeout.command:" + comm);
                    return null;
                }
            }
            if (inputStream.available() > 0) {
                while (length <= 0) {
                    length = inputStream.read(content);
                    if (new Date().getTime() >= time + receiveDataTimeout) {
                        log.error("Receiving data timeout.command:" + comm);
                        return null;
                    }
                }
            }
            byte[] data = Arrays.copyOfRange(content, 0, length);
            log.info("Receive data: " + CRC16.bytesToString(data));
            return data;
        } catch (InterruptedException e) {
            log.error(e.getMessage());
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            log.error(e.getMessage());
            e.printStackTrace();
            return null;
        }


    }

    private void closeSocket() {
        try {
            if (inputStream != null) {
                inputStream.close();
                inputStream = null;
            }
            if (outputStream != null) {
                outputStream.close();
                outputStream = null;
            }
            if (socket != null) {
                socket.close();
            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }


//    private void sendCommd(String commd) {
//        try {
//            isTimeout = !semaphore.tryAcquire(receiveDataTimeout, TimeUnit.MILLISECONDS);
//            if (isTimeout) {
//                log.error("Receiving data timeout.command:" + currentCommand);
//                //批量设备离线
//                if (currentCommand.length() >= 2) {
//                    List<MotorMonitor> motorMonitors = motorsMapper.motorMoniSelect(currentCommand.substring(0, 2), converterTypeE);
//                    List<MoAlertRec> moAlertRecs = new ArrayList<>();
//                    List<Integer> offlineMotorIds = new ArrayList<>();
//                    for (MotorMonitor motorMonitor : motorMonitors) {
//                        if (motorMonitor.getMoState() != 3 && motorMonitor.getMoState() != 0) {
//                            //连续异常 再报警
//                            if (motorOfflineTimes.get(motorMonitor.getMoId()) == null) {
//                                motorOfflineTimes.put(motorMonitor.getMoId(), 1);
//                            } else if (motorOfflineTimes.get(motorMonitor.getMoId()) < getOfflineTimes()) {
//                                motorOfflineTimes.put(motorMonitor.getMoId(), motorOfflineTimes.get(motorMonitor.getMoId()) + 1);
//                            } else if (motorOfflineTimes.get(motorMonitor.getMoId()) >= getOfflineTimes()) {
//                                if (isAlarmOffline != 0) {
//                                    MoAlertRec alertRec = new MoAlertRec(ALERT_CALSS_OFFLINE, motorMonitor.getMoId(), motorMonitor.getMoName(), motorMonitor.getAreaId(),
//                                            motorMonitor.getAreaName(), new Date(), BigDecimal.valueOf(0), motorMonitor.getUpperLimit(), motorMonitor.getLowerLimit(), 0,
//                                            motorMonitor.getAreaName() + "->" + motorMonitor.getMoName() + "马达离线，没有数据！");
//                                    moAlertRecs.add(alertRec);
//                                }
//                                offlineMotorIds.add(motorMonitor.getMoId());
//                                motorOfflineTimes.put(motorMonitor.getMoId(), 0);
//                            }
//                        }
//                    }
//                    if (moAlertRecs.size() > 0) {
//                        alertRecMapper.insertBatch(moAlertRecs);
//                    }
//                    if (offlineMotorIds.size() > 0) {
//                        motorsMapper.updateStateByIds(0, "gray", offlineMotorIds);
//                    }
//                }
//            }
//            log.info("Receive data start......");
//            if (!isOpen) {
//                portList = CommPortIdentifier.getPortIdentifiers();
//                while (portList.hasMoreElements()) {
//                    CommPortIdentifier port = portList.nextElement();
//                    if (port.getPortType() == CommPortIdentifier.PORT_SERIAL && rxdCOMe.equals(port.getName())) {
//
//                        serialPort = (SerialPort) port.open(Object.class.getSimpleName(), 2000);
//                        serialPort.addEventListener(this);
//                        serialPort.notifyOnDataAvailable(true);
//                        serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
//                                SerialPort.PARITY_NONE);
//                        isOpen = true;
//                    }
//                }
//            }
//            if (isOpen) {
//                outputStream = serialPort.getOutputStream();
//                outputStream.write(CRC16.command2Bytes(commd));
//                currentCommand = commd;
//            }
//        } catch (IOException e) {
//            log.error(e.getMessage());
//            closeSerialPort();
//            isOpen = false;
//            e.printStackTrace();
//        } catch (TooManyListenersException e) {
//            log.error(e.getMessage());
//            closeSerialPort();
//            isOpen = false;
//            e.printStackTrace();
//        } catch (InterruptedException e) {
//            log.error(e.getMessage());
//            closeSerialPort();
//            isOpen = false;
//            e.printStackTrace();
//        } catch (PortInUseException e) {
//            log.error(e.getMessage());
//            closeSerialPort();
//            isOpen = false;
//            e.printStackTrace();
//        } catch (UnsupportedCommOperationException e) {
//            log.error(e.getMessage());
//            closeSerialPort();
//            isOpen = false;
//            e.printStackTrace();
//        } catch (Exception e) {
//            log.error(e.getMessage());
//            closeSerialPort();
//            isOpen = false;
//            e.printStackTrace();
//        }
//
//    }
//
//    public void serialEvent(SerialPortEvent event) {
//        switch (event.getEventType()) {
//            case SerialPortEvent.BI:/* Break interrupt,通讯中断 */
//            case SerialPortEvent.OE:/* Overrun error，溢位错误 */
//            case SerialPortEvent.FE:/* Framing error，传帧错误 */
//            case SerialPortEvent.PE:/* Parity error，校验错误 */
//            case SerialPortEvent.CD:/* Carrier detect，载波检测 */
//            case SerialPortEvent.CTS:/* Clear to send，清除发送 */
//            case SerialPortEvent.DSR:/* Data set ready，数据设备就绪 */
//            case SerialPortEvent.RI:/* Ring indicator，响铃指示 */
//            case SerialPortEvent.OUTPUT_BUFFER_EMPTY:/* Output buffer is empty，输出缓冲区清空 */
//                break;
//            case SerialPortEvent.DATA_AVAILABLE:/* Data available at the serial port，端口有可用数据。读到缓冲数组，输出到终端 */
//                //模块类型不同，返回长度不同
//                byte[] readBuffer = new byte[9];
//                try {
//                    Thread.sleep(100);
//                    inputStream = serialPort.getInputStream();
//                    while (inputStream.read(readBuffer) != -1) {
//                        log.info("Receive data: " + CRC16.bytesToString(readBuffer));
//                        Date recTime = new Date();
//                        if (CRC16.checkCRC2(readBuffer)) {
//                            addr = CRC16.bytesToString(new byte[]{readBuffer[0]}).trim();
//                            int[] data = CRC16.byte2Info(Arrays.copyOfRange(readBuffer, 3, 7));
//                            RawData rawData = new RawData(addr, data[0], data[1], new Date());
//                            if (!queue.offer(rawData)) {
//                                log.error("Data queue full!!!size:" + queue.size());
//                                queue.poll();
//                                queue.offer(rawData);
//                            }
//                            log.info("Receive data:addr=" + rawData.getAddr() + ",data1=" + rawData.getData().get(0) + ",data2=" + rawData.getData().get(1) + "------queue size:" + queue.size());
//                        }
//                        break;
//                    }
//                } catch (IOException e) {
//                    log.error(e.getMessage());
//                    closeSerialPort();
//                    isOpen = false;
//                    e.printStackTrace();
//                } catch (InterruptedException e) {
//                    log.error(e.getMessage());
//                    closeSerialPort();
//                    isOpen = false;
//                    e.printStackTrace();
//                } catch (Exception e) {
//                    log.error(e.getMessage());
//                    closeSerialPort();
//                    isOpen = false;
//                    e.printStackTrace();
//                } finally {
//                    semaphore.release();
//                }
//                log.info("Receive data end......");
//        }
//    }
//
//    public void closeSerialPort() {
//        if (serialPort != null) {
//            serialPort.notifyOnDataAvailable(false);
//            serialPort.removeEventListener();
//            if (inputStream != null) {
//                try {
//                    inputStream.close();
//                    inputStream = null;
//                } catch (IOException e) {
//                    log.error(e.getMessage());
//                }
//            }
//            if (outputStream != null) {
//                try {
//                    outputStream.close();
//                    outputStream = null;
//                } catch (IOException e) {
//                    log.error(e.getMessage());
//                }
//            }
//            serialPort.close();
//            serialPort = null;
//        }
//    }

    /**
     * @Description:
     * @Param:
     * @return:
     * @Author: your name
     * @date: 2020/6/20
     */
    @Override
    public boolean saveData() {
        log.info("Save data start......");
        List<MoDataRec> moDataRecs = new ArrayList<>();
        List<MoAlertRec> moAlertRecs = new ArrayList<>();
        List<Integer> exceptionMotorIds = new ArrayList<>();
        List<Integer> exceptionMotorIdsRecovery = new ArrayList<>();
        List<Integer> offlineMotorIds = new ArrayList<>();
        List<Integer> offlineMotorIdsRecovery = new ArrayList<>();
        RawData data = queue.poll();
        while (data != null) {
            List<MotorMonitor> motorMonitors = motorsMapper.motorMoniSelect(data.getAddr(), converterTypeE);
            MoDataRec rec;
            for (MotorMonitor motorMonitor : motorMonitors) {
                int k = data.getData().get(motorMonitor.getBitSn() - 1);
                //3>0>2>1 3保养
                if (motorMonitor.getMoState() == 3) {
                    continue;
                }

                //0传感器离线
                if (k >= 65525 || k <= 10) {
                    // List<MoAlertRec> alertRecs=alertRecMapper.selectUntreated(motorMonitor.getMoId());
                    // if(alertRecs.size()==0)
                    if (motorMonitor.getMoState() != 0) {
                        //连续异常 再报警
                        if (motorOfflineTimes.get(motorMonitor.getMoId()) == null) {
                            motorOfflineTimes.put(motorMonitor.getMoId(), 1);
                        } else if (motorOfflineTimes.get(motorMonitor.getMoId()) < getOfflineTimes()) {
                            motorOfflineTimes.put(motorMonitor.getMoId(), motorOfflineTimes.get(motorMonitor.getMoId()) + 1);
                        } else if (motorOfflineTimes.get(motorMonitor.getMoId()) >= getOfflineTimes()) {
                            if (isAlarmOffline != 0) {
                                MoAlertRec alertRec = new MoAlertRec(ALERT_CALSS_OFFLINE, motorMonitor.getMoId(), motorMonitor.getMoName(), motorMonitor.getAreaId(),
                                        motorMonitor.getAreaName(), new Date(), BigDecimal.valueOf(0), motorMonitor.getUpperLimit(), motorMonitor.getLowerLimit(), 0,
                                        motorMonitor.getAreaName() + "->" + motorMonitor.getMoName() + "馬達離線，沒有數據！");
                                moAlertRecs.add(alertRec);
                            }
                            offlineMotorIds.add(motorMonitor.getMoId());
                            motorOfflineTimes.put(motorMonitor.getMoId(), 0);
                        }
                    }
                    continue;
                } else {
                    //离线恢复
                    motorOfflineTimes.put(motorMonitor.getMoId(), 0);
                    if (motorMonitor.getMoState() == 0) {
                        offlineMotorIdsRecovery.add(motorMonitor.getMoId());
                    }
                }

                //2、1 异常、正常
                rec = new MoDataRec(motorMonitor.getMoId(), motorMonitor.getMoName(), motorMonitor.getAreaId(), motorMonitor.getAreaName(),
                        motorMonitor.getMonitorId(), data.getRecTime(), motorMonitor.getUpperLimit(), motorMonitor.getLowerLimit(), motorMonitor.getMoState(), motorMonitor.getFixBase());
                float value = 0;
                if (k > motorMonitor.getInputTo()) {
                    value = motorMonitor.getValueTo();
                } else if (k < motorMonitor.getInputFrom()) {
                    value = motorMonitor.getValueFrom();
                } else {
                    float avg = (motorMonitor.getInputTo() - motorMonitor.getInputFrom()) / (motorMonitor.getValueTo() - motorMonitor.getValueFrom());
                    value = ((float) k / avg - motorMonitor.getInputFrom() / avg);
                }
                rec.setOrigData(BigDecimal.valueOf(value));
                BigDecimal sdata = rec.getOrigData().add(rec.getFixBase());
                if (sdata.compareTo(BigDecimal.valueOf(motorMonitor.getValueFrom())) == -1 || sdata.compareTo(BigDecimal.valueOf(motorMonitor.getValueFrom())) == 0) {
                    rec.setRockData(BigDecimal.valueOf(motorMonitor.getValueFrom()));
                } else if (sdata.compareTo(BigDecimal.valueOf(motorMonitor.getValueTo())) == 1 || sdata.compareTo(BigDecimal.valueOf(motorMonitor.getValueTo())) == 0) {
                    rec.setRockData(BigDecimal.valueOf(motorMonitor.getValueTo()));
                } else {
                    rec.setRockData(sdata);
                }
                if (motorMonitor.getUpperLimit().compareTo(BigDecimal.valueOf(-1)) != 0 && rec.getRockData().compareTo(motorMonitor.getUpperLimit()) == 1) {
                    rec.setIsOver(1);
                }
                if (motorMonitor.getLowerLimit().compareTo(BigDecimal.valueOf(-1)) != 0 && rec.getRockData().compareTo(motorMonitor.getLowerLimit()) == -1) {
                    rec.setIsOver(1);
                }
                log.info("Save data:moid=" + rec.getMoId() + ",moName=" + rec.getMoName() + ",rockData=" + rec.getRockData() + ",limit=" + rec.getLowerLimit() + "~~" + rec.getUpperLimit());
                //洪总命令一分钟内保留一条数据，减少数据库数据
                if (motorRecTimes.get(rec.getMoId()) == null) {
                    motorRecTimes.put(rec.getMoId(), 1);
                } else {
                    motorRecTimes.put(rec.getMoId(), motorRecTimes.get(rec.getMoId()) + 1);
                }
                if (motorRecTimes.get(rec.getMoId()) >= getSaveTimes()) {
                    moDataRecs.add(rec);
                    motorRecTimes.put(rec.getMoId(), 0);
                }
                //判断报警
                if (motorMonitor.getMoState() == 1 && (motorMonitor.getLowerLimit().compareTo(BigDecimal.valueOf(-1)) != 0 || motorMonitor.getUpperLimit().compareTo(BigDecimal.valueOf(-1)) != 0)) {
                    if (motorMonitor.getUpperLimit().compareTo(BigDecimal.valueOf(-1)) != 0 && rec.getRockData().compareTo(motorMonitor.getUpperLimit()) == 1) {
                        //连续异常 再报警
                        if (motorExceptionTimes.get(motorMonitor.getMoId()) == null) {
                            motorExceptionTimes.put(motorMonitor.getMoId(), 1);
                        } else if (motorExceptionTimes.get(motorMonitor.getMoId()) < getExceptionTimes()) {
                            motorExceptionTimes.put(motorMonitor.getMoId(), motorExceptionTimes.get(motorMonitor.getMoId()) + 1);
                        } else if (motorExceptionTimes.get(motorMonitor.getMoId()) >= getExceptionTimes()) {
                            MoAlertRec alertRec = new MoAlertRec(ALERT_CALSS_EXCEED, motorMonitor.getMoId(), motorMonitor.getMoName(), motorMonitor.getAreaId(),
                                    motorMonitor.getAreaName(), new Date(), rec.getRockData(), motorMonitor.getUpperLimit(), motorMonitor.getLowerLimit(), 0,
                                    motorMonitor.getAreaName() + "->" + motorMonitor.getMoName() + "馬達故障、螺絲鬆動！");
                            moAlertRecs.add(alertRec);
                            exceptionMotorIds.add(motorMonitor.getMoId());
                            motorExceptionTimes.put(motorMonitor.getMoId(), 0);
                            sqlServer.addNotes(getMobiles(), motorMonitor.getAreaName() + "->" + motorMonitor.getMoName() + "馬達故障、螺絲鬆動！！");
                        }

                    } else if (motorMonitor.getLowerLimit().compareTo(BigDecimal.valueOf(-1)) != 0 && rec.getRockData().compareTo(motorMonitor.getLowerLimit()) == -1) {
                        //连续异常 再报警
                        if (motorExceptionTimes.get(motorMonitor.getMoId()) == null) {
                            motorExceptionTimes.put(motorMonitor.getMoId(), 1);
                        } else if (motorExceptionTimes.get(motorMonitor.getMoId()) < getExceptionTimes()) {
                            motorExceptionTimes.put(motorMonitor.getMoId(), motorExceptionTimes.get(motorMonitor.getMoId()) + 1);
                        } else if (motorExceptionTimes.get(motorMonitor.getMoId()) >= getExceptionTimes()) {
                            MoAlertRec alertRec = new MoAlertRec(ALERT_CALSS_EXCEED, motorMonitor.getMoId(), motorMonitor.getMoName(), motorMonitor.getAreaId(),
                                    motorMonitor.getAreaName(), new Date(), rec.getRockData(), motorMonitor.getUpperLimit(), motorMonitor.getLowerLimit(), 0,
                                    motorMonitor.getAreaName() + "->" + motorMonitor.getMoName() + "馬達停機！");
                            moAlertRecs.add(alertRec);
                            exceptionMotorIds.add(motorMonitor.getMoId());
                            motorExceptionTimes.put(motorMonitor.getMoId(), 0);
                            sqlServer.addNotes(getMobiles(), motorMonitor.getAreaName() + "->" + motorMonitor.getMoName() + "馬達停機！");
                        }
                    }
                } else if (motorMonitor.getMoState() == 2) {
                    //报警恢复
                    boolean isOk = false;
                    if (motorMonitor.getLowerLimit().compareTo(BigDecimal.valueOf(-1)) == 0 && motorMonitor.getUpperLimit().compareTo(BigDecimal.valueOf(-1)) == 0) {
                        isOk = true;
                    } else if (motorMonitor.getLowerLimit().compareTo(BigDecimal.valueOf(-1)) == 0 && motorMonitor.getUpperLimit().compareTo(BigDecimal.valueOf(-1)) != 0) {
                        if (rec.getRockData().compareTo(motorMonitor.getUpperLimit()) == -1 || rec.getRockData().compareTo(motorMonitor.getUpperLimit()) == 0) {
                            isOk = true;
                        }
                    } else if (motorMonitor.getLowerLimit().compareTo(BigDecimal.valueOf(-1)) != 0 && motorMonitor.getUpperLimit().compareTo(BigDecimal.valueOf(-1)) == 0) {
                        if (rec.getRockData().compareTo(motorMonitor.getLowerLimit()) == 1 || rec.getRockData().compareTo(motorMonitor.getLowerLimit()) == 0) {
                            isOk = true;
                        }
                    } else {
                        if ((rec.getRockData().compareTo(motorMonitor.getLowerLimit()) == 1 || rec.getRockData().compareTo(motorMonitor.getLowerLimit()) == 0) && (rec.getRockData().compareTo(motorMonitor.getUpperLimit()) == -1 || rec.getRockData().compareTo(motorMonitor.getUpperLimit()) == 0)) {
                            isOk = true;
                        }
                    }
                    if (isOk) {
                        //连续恢复 再恢复
                        if (motorRecoveryTimes.get(motorMonitor.getMoId()) == null) {
                            motorRecoveryTimes.put(motorMonitor.getMoId(), 1);
                        } else if (motorRecoveryTimes.get(motorMonitor.getMoId()) < getRecoveryTimes()) {
                            motorRecoveryTimes.put(motorMonitor.getMoId(), motorRecoveryTimes.get(motorMonitor.getMoId()) + 1);
                        } else if (motorRecoveryTimes.get(motorMonitor.getMoId()) >= getRecoveryTimes()) {
                            exceptionMotorIdsRecovery.add(motorMonitor.getMoId());
                            motorRecoveryTimes.put(motorMonitor.getMoId(), 0);
                        }
                    }
                }
            }
            data = queue.poll();
        }
        if (moDataRecs.size() > 0) {
            //batch insert
            dataRecMapper.insertBatch(moDataRecs);
        }
        if (moAlertRecs.size() > 0) {
            //状态覆盖，低等级异常自动关闭
            alertRecMapper.updateRecoveryByRecs(new Date(), "状态覆盖,产生新异常。", moAlertRecs);
            alertRecMapper.insertBatch(moAlertRecs);
        }
        if (offlineMotorIds.size() > 0) {
            motorsMapper.updateStateByIds(0, "gray", offlineMotorIds);
        }
        if (offlineMotorIdsRecovery.size() > 0) {
            if (isAlarmOffline != 0) {
                alertRecMapper.updateRecoveryByIds(new Date(), "离线设备恢复正常！", 3, offlineMotorIdsRecovery);
            }
            motorsMapper.updateStateByIds(1, "green", offlineMotorIdsRecovery);
        }
        if (exceptionMotorIds.size() > 0) {
            motorsMapper.updateStateByIds(2, "red", exceptionMotorIds);
        }
        if (exceptionMotorIdsRecovery.size() > 0) {
            motorsMapper.updateStateByIds(1, "green", exceptionMotorIdsRecovery);
            alertRecMapper.updateRecoveryByIds(new Date(), "马达恢复正常！", 1, exceptionMotorIdsRecovery);
        }

        log.info("Save data end......");
        //更新报警灯状态
        if (motorsMapper.countAlarmMotor() > 0) {
            alarmLampServiceImpSerialPort.openAlarmLamp();
        } else {
            alarmLampServiceImpSerialPort.closeAlarmLamp();
        }
        return true;
    }

    /**
     * @Description: 重新获取系统配置
     * @Param:
     * @return:
     * @Author: 黄国健
     * @date: 2020/7/6
     */
    public void clearConf() {
        offlineTimes = 0;
        exceptionTimes = 0;
        recoveryTimes = 0;
    }
}
